package cc.autoapi.pucong.auto.flow.provider.api.manager;


import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.aop.TaskAopInfoVo;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.task.ApiExecResult;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exec.DataBus;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exec.ProcessExecStart;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.selfenum.RunStatusEnum;
import cc.autoapi.pucong.auto.flow.core.root.exception.AutoFlowException;
import cc.autoapi.pucong.auto.flow.core.root.selfenum.ApiTypeEnum;
import cc.autoapi.pucong.auto.flow.core.root.selfenum.CommonBoolenEnum;
import cc.autoapi.pucong.auto.flow.core.root.utils.UUID;
import cc.autoapi.pucong.auto.flow.persistence.po.api.ApiInfoPo;
import cc.autoapi.pucong.auto.flow.persistence.repository.api.ApiInfoService;
import cc.autoapi.pucong.auto.flow.persistence.repository.api.ApiNodeService;
import cc.autoapi.pucong.auto.flow.persistence.repository.api.AutoFlowAuthInterceptor;
import cc.autoapi.pucong.auto.flow.persistence.repository.log.ApiInstanceNodeService;
import cc.autoapi.pucong.auto.flow.persistence.repository.log.ApiInstanceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author pucong
 * @description 接口信息 managerService 实现类
 * @create 2024-09-24
 */
@Service
@Slf4j
public class ApiExecManager {


    @Resource
    private ApiInfoService apiInfoService;

    @Resource
    private ApiNodeService apiNodeService;

    @Resource
    private ApiInstanceService apiInstanceService;

    @Resource
    private AutoFlowAuthInterceptor autoFlowAuthInterceptor;

    @Resource
    private ApiInstanceNodeService apiInstanceNodeService;

    @Value("${server.servlet.context-path}")
    private String systemPath;

    public Object serviceExec(HttpServletRequest request,
                              Map<String, String> headerMap,
                              Map<String, Object> bodyMap,
                              Map<String, Object> queryMap) {
        String requestURI = request.getRequestURI();
        String accessUrl = requestURI.replaceAll(systemPath + "/api/exec/apiExec/", "")
                .replaceAll(systemPath + "/api/exec/apiExecStream/", "");
        // 获取访问方式
        String method = request.getMethod();
        ApiTypeEnum requestMethod = ApiTypeEnum.POST;
        if ("POST".equals(method)) {
            requestMethod = ApiTypeEnum.POST;
        } else if ("DELETE".equals(method)) {
            requestMethod = ApiTypeEnum.DELETE;
        } else if ("GET".equals(method)) {
            requestMethod = ApiTypeEnum.GET;
        } else if ("PUT".equals(method)) {
            requestMethod = ApiTypeEnum.PUT;
        }

        ApiInfoPo apiInfoPo = apiInfoService.getOneByCodesAndType(new String[]{accessUrl, "/" + accessUrl}, requestMethod);
        if (apiInfoPo == null) {
            throw new AutoFlowException("传入参数错误");
        }
        if (apiInfoPo.getApiStatus() == CommonBoolenEnum.否) {
            throw new AutoFlowException("已禁用，无法使用");
        }
        // 校验授权token
        Boolean hasPermission = autoFlowAuthInterceptor.checkExecPermission(request, apiInfoPo);
        if (!hasPermission) {
            throw new AutoFlowException("无权限使用，请联系管理员");
        }
        // 创建实例信息
        String instanceId = UUID.uuid();
        // aop 前置执行
        doAopBeforeExec(apiInfoPo.getUuid(), queryMap, headerMap, bodyMap);
        // 开始执行
        ProcessExecStart processExecStart = new ProcessExecStart(apiInfoPo.getUuid(), instanceId, queryMap, headerMap, bodyMap);
        ApiExecResult result = null;
        try {
            result = processExecStart.start();
        } catch (Exception e) {
            log.error("执行服务异常: ", e);
            throw new AutoFlowException("执行失败,", e.getMessage());
        }
        RunStatusEnum runStatus = result.getRunStatus();
        if (runStatus == RunStatusEnum.执行成功) {
            Object data = result.getData();
            return data;
        } else if (runStatus == RunStatusEnum.执行失败) {
            throw new AutoFlowException(result.getErrorLog());
        }
        // aop 后置执行
        doAopAfterExec(apiInfoPo.getUuid(), queryMap, headerMap, bodyMap);
        return null;
    }

    private void doAopAfterExec(String uuid,
                                Map<String, Object> queryMap,
                                Map<String, String> headerMap,
                                Map<String, Object> bodyMap) {
        List<TaskAopInfoVo> taskAopList = DataBus.getTaskAopList(uuid);
        if (taskAopList == null) {
            return;
        }
        List<TaskAopInfoVo> taskAopInfoVos = taskAopList.stream().filter(taskAopInfoVo -> taskAopInfoVo.getAopPosition() == 1).collect(Collectors.toList());
        for (TaskAopInfoVo taskAopInfoVo : taskAopInfoVos) {
            /**
             * 执行
             */
            // 创建实例信息
            String instanceId = UUID.uuid();
            ProcessExecStart processExecStart = new ProcessExecStart(taskAopInfoVo.getApiId(), instanceId, queryMap, headerMap, bodyMap);
            ApiExecResult result = null;
            try {
                result = processExecStart.start();
            } catch (Exception e) {
                log.error("执行服务异常: ", e);
                throw new AutoFlowException("执行失败,", e.getMessage());
            }
            RunStatusEnum runStatus = result.getRunStatus();
            if (runStatus == RunStatusEnum.执行失败) {
                throw new AutoFlowException(result.getErrorLog());
            }
        }
    }

    private void doAopBeforeExec(String uuid,
                                 Map<String, Object> queryMap,
                                 Map<String, String> headerMap,
                                 Map<String, Object> bodyMap) {

        List<TaskAopInfoVo> taskAopList = DataBus.getTaskAopList(uuid);
        if (taskAopList == null) {
            return;
        }
        List<TaskAopInfoVo> taskAopInfoVos = taskAopList.stream().filter(taskAopInfoVo -> taskAopInfoVo.getAopPosition() == 0).collect(Collectors.toList());
        for (TaskAopInfoVo taskAopInfoVo : taskAopInfoVos) {
            /**
             * 执行
             */
            // 创建实例信息
            String instanceId = UUID.uuid();
            ProcessExecStart processExecStart = new ProcessExecStart(taskAopInfoVo.getApiId(), instanceId, queryMap, headerMap, bodyMap);
            ApiExecResult result = null;
            try {
                result = processExecStart.start();
            } catch (Exception e) {
                log.error("执行服务异常: ", e);
                throw new AutoFlowException("执行失败,", e.getMessage());
            }
            // 执行失败获取状态为false，则不继续执行
            RunStatusEnum runStatus = result.getRunStatus();
            if (runStatus == RunStatusEnum.执行失败) {
                throw new AutoFlowException(result.getErrorLog());
            }
        }
    }
}
